import * as THREE from 'three'
import { JueSe } from "./JueSe.js"
import { GangTi } from "./GangTi.js"
import { RouTi } from "./RouTi.js"
import { FaGuangTi } from "./FaGuangTi.js"
import { YueShu } from '../yueShu/YueShu.js'
import { huanJing } from '../../huanJing/HuanJing'
import { wanZhengDiZhi } from '../../gongJu/gongJu.js'

export let wanJia = null

// 玩家处于世界坐标系
export class WanJia extends JueSe {
	shiWanJia = true
	xiangJiFuZhu = new THREE.Object3D() // 玩家控制相机辅助对象
	dianGuangYuan = null // 照明光源
	pingXingGuang = null // 投影光源
	huanJingGuang = new THREE.AmbientLight(0xccbbaa, 0.3) // 环境光
	shouGuangHengXing = null // 受光恒星
	piFeng = null // 披风
	
	constructor(banJing = 0.5, gao = 1) {
		super(banJing, gao)

		this.jiaZaiMoXing(wanZhengDiZhi('./moXing/wo.glb')).then(res => {
			this.xiangJiFuZhu.rotateY(Math.PI)
			let chuShiWeiZhi = new THREE.Vector3(0, (banJing + gao) / 2, banJing)
			this.xiangJiFuZhu.position.copy(chuShiWeiZhi)
			this.xiangJiFuZhu.userData.chuShiWeiZhi = chuShiWeiZhi
			this.moXing.add(this.xiangJiFuZhu)
			this.moXing.traverse(w => {
				w.userData.chuanMo = true // 镜头防穿模不检测
			})
		})
		
		wanJia = this

		this.tianJiaJianTingQi('jiaZaiMoXing', () => {
			this.touYing()
		})
		// 柔体锚点、约束 设置位置有异步延迟，锚点物体过远有问题，不好解决
		this.tianJiaJianTingQi('sheZhiWuTi', shiJian => {
			if (shiJian.canShu.weiZhi) {
				this.xiaCiGengXinHou = () => {
					setTimeout(() => this.zhaoMingDeng(), 500)
					// this.zhaoMingDeng()
					// this.piFengJiaZai()
					// this.rouTiKuai()
				}
			}
		})
		
		huanJing.scene.add(this.huanJingGuang)
	}
	
	// 平行投影光 跟恒星光效果有冲突
	touYing() {
		if (!this.pingXingGuang) {
			// 跟随人物产生阴影
			let pingXingGuang = new THREE.DirectionalLight(0xffeedd, 2)
			pingXingGuang.castShadow = true
			const d = 50
			// shadow.camera范围内才有阴影
			pingXingGuang.shadow.camera.near = 0.5
			pingXingGuang.shadow.camera.far = 2000
			pingXingGuang.shadow.camera.right = d
			pingXingGuang.shadow.camera.left = -d
			pingXingGuang.shadow.camera.top = d
			pingXingGuang.shadow.camera.bottom = -d
			pingXingGuang.shadow.mapSize.width = (d / 10) * 1024
			pingXingGuang.shadow.mapSize.height = (d / 10) * 1024
			pingXingGuang.shadow.bias = -0.00001
			
			pingXingGuang.target = this.moXing
			this.pingXingGuang = pingXingGuang
		}
		huanJing.scene.add(this.pingXingGuang)
	}
	// 阴影跟随
	yinYingGenSui() {
		if (!(this.shouGuangHengXing && this.pingXingGuang)) return
		
		let hengXingWeiZhi = this.shouGuangHengXing.moXing.getWorldPosition(new THREE.Vector3())
		let wanJiaWeiZhi = this.moXing.getWorldPosition(new THREE.Vector3())
		let chaoXiang = new THREE.Vector3().subVectors(hengXingWeiZhi, wanJiaWeiZhi).normalize().multiplyScalar(1000)
		
		this.pingXingGuang.position.copy(this.moXing.position).add(chaoXiang)
	}
	// 披风；设置玩家位置后，没锚点的披风不会跟随
	piFengJiaZai() {
		if (!this.piFeng) {
			const clothWidth = 0.6;
			const clothHeight = 1.5;
			const clothNumSegmentsX = 10;
			const clothNumSegmentsY = 20;
			const clothPos = new THREE.Vector3( 0, 0, -0.6 );
			
			const clothGeometry = new THREE.PlaneGeometry( clothWidth, clothHeight, clothNumSegmentsX, clothNumSegmentsY );
			const clothMaterial = new THREE.MeshLambertMaterial( { color: 0xaabbff, side: THREE.DoubleSide } );
			let cloth = new THREE.Mesh( clothGeometry, clothMaterial );
			cloth.position.copy(clothPos)
			cloth.castShadow = true;
			cloth.receiveShadow = true;
			cloth.userData.xingZhuang = '面'
			cloth.userData.chuanMo = true
			
			let piFeng = new RouTi(cloth, 1)
			piFeng.mingZi = '披风'
			piFeng.fu = this
			this.zi.add(piFeng)
			this.piFeng = piFeng
		} else this.piFeng.xieZai()

		this.piFeng.jiaZai(this.moXing)
		this.piFeng.sheZhiPengZhuangTi({
			mao: [ { suoYin: 0, wuTiBianHao: this.bianHao }, { suoYin: 10, wuTiBianHao: this.bianHao } ]
		})
	}
	// 照明灯
	zhaoMingDeng() {
		if (!this.dianGuangYuan) {
			// 灯杆
			const bgeometry = new THREE.BoxGeometry( 0.05, 0.05, 0.5 );
			const bmaterial = new THREE.MeshStandardMaterial({color: 0x9999aa})
			const box = new THREE.Mesh( bgeometry, bmaterial )
			box.position.set(-0.25, 0, 0.25)
			let bpengZhuang = box.clone()
			bpengZhuang.userData.xingZhuang = '方体'
			let gan = new GangTi(box, bpengZhuang, 0.1)
			gan.fu = this
			this.zi.add(gan)
			gan.jiaZai()
			// 灯
			const geometry = new THREE.SphereGeometry( 0.1, 64, 32 );
			const material = new THREE.MeshStandardMaterial({ color: 0xffffff, opacity: 0.5, transparent: true })
			const sphere = new THREE.Mesh( geometry, material )
			sphere.position.set(-0.25, -0.3, 0.5)
			let pengZhuang = sphere.clone()
			pengZhuang.userData.xingZhuang = '球体'
			let dianGuangYuan = new FaGuangTi(sphere, pengZhuang, 0.1, 0xccbbaa, 50, 100)
			dianGuangYuan.mingZi = '照明灯'
			dianGuangYuan.fu = this
			this.zi.add(dianGuangYuan)
			dianGuangYuan.jiaZai()
			this.dianGuangYuan = dianGuangYuan
			// 线
			const ropeNumSegments = 5;
			const ropeLength = 0.2;
			const ropeMass = 0.1;
			const ropePos = new THREE.Vector3( -0.25, 0, 0.5 );
			const segmentLength = ropeLength / ropeNumSegments;
			const ropeGeometry = new THREE.BufferGeometry();
			const ropeMaterial = new THREE.LineBasicMaterial( { color: 0xffffaa } );
			const ropePositions = [];
			const ropeIndices = [];
			for ( let i = 0; i < ropeNumSegments + 1; i ++ ) {
				ropePositions.push( 0, i * segmentLength, 0);
			}
			for ( let i = 0; i < ropeNumSegments; i ++ ) {
				ropeIndices.push( i, i + 1 );
			}
			ropeGeometry.setIndex( new THREE.BufferAttribute( new Uint16Array( ropeIndices ), 1 ) );
			ropeGeometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( ropePositions ), 3 ) );
			ropeGeometry.computeBoundingSphere();
			let rope = new THREE.LineSegments( ropeGeometry, ropeMaterial );
			rope.position.copy(ropePos)
			rope.castShadow = true;
			rope.receiveShadow = true;
			
			let moWeiZhi = ropePos.clone()
			moWeiZhi.y -= ropeLength
			rope.userData.xingZhuang = '线'
			rope.userData.xian = {
				moWeiZhi,
				duanShu: ropeNumSegments
			}
			let rp = new RouTi(rope, ropeMass)
			rp.fu = this
			this.zi.add(rp)
			rp.jiaZai()
			rp.sheZhiPengZhuangTi({
				mao: [ { suoYin: 0, wuTiBianHao: gan.bianHao }, { suoYin: ropeNumSegments, wuTiBianHao: dianGuangYuan.bianHao } ]
			})
			
			// 约束
			let yueShu = new YueShu('铰链', {
				wuTiA: this,
				wuTiB: gan,
				weiZhiA: new THREE.Vector3(-0.3, 0, 0),
				weiZhiB: new THREE.Vector3(0, 0, -0.25),
				zuoBiaoZhouA: new THREE.Vector3(0, 1, 0),
				zuoBiaoZhouB: new THREE.Vector3(0, 1, 0)
			}, true)
			yueShu.jiaZai()
			yueShu.sheZhiYueShu({
				jiaoLian: {
					xuanZhuanFanWei: { zuiXiao: -0.2, zuiDa: -0.2},
					xuanZhuanSuDu: 0
				}
			})
		}

		if (this.dianGuangYuan.liang) this.dianGuangYuan.faGuang(false)
		else this.dianGuangYuan.faGuang(true)
	}
	// 柔体块
	rouTiKuai() {
		// 世界坐标系
		const boxGeometry = new THREE.BoxGeometry( 1, 1, 5, 4, 4, 20 );
		let weiZhi = this.moXing.getWorldPosition(new THREE.Vector3())
		weiZhi.z += 10
		boxGeometry.translate(...weiZhi.toArray());
		const bmaterial = new THREE.MeshStandardMaterial( {color: 0xff00aa } )
		const box = new THREE.Mesh( boxGeometry, bmaterial )
		box.userData.xingZhuang = '体'
		let boxt = new RouTi(box, 15)
		boxt.jiaZai()
	}
	
	gengXin(jianGeShi) {
		super.gengXin(jianGeShi)
		
		this.yinYingGenSui()
	}
	
}